package com.edu.internship.busi.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.edu.internship.config.cache.GuavaCache;
import com.edu.internship.busi.dto.DictionaryDTO;
import com.edu.internship.busi.entity.Dictionary;
import com.edu.internship.busi.entity.DictionaryOption;
import com.edu.internship.config.redis.RedisUtil;
import com.edu.internship.glabal.constants.Constants;
import com.edu.internship.glabal.constants.ResultCodeEnum;
import com.edu.internship.glabal.exception.BusinessException;
import com.edu.internship.busi.mapper.DictionaryMapper;
import com.edu.internship.busi.service.IDictionaryOptionService;
import com.edu.internship.busi.service.IDictionaryService;
import com.edu.internship.util.BeanExUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * code is far away from bug with the animal protecting
 *
 * @author lishiquan
 * @description <p>Dictionary 的serviceImpl</p>
 * @date 2020-07-03
 */
@Service
@Slf4j
public class DictionaryServiceImpl extends ServiceImpl<DictionaryMapper, Dictionary> implements IDictionaryService {

//    @Resource
//    private GuavaCache guavaCache;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private IDictionaryOptionService dictionaryOptionService;

    @Override
    @Transactional(rollbackFor = BusinessException.class)
    public void createDictionary(DictionaryDTO dto) {
        Dictionary dictionary = this.nonExistsAndConvert(dto);
        dictionary.setCreateTime(LocalDateTime.now());
        super.save(dictionary);
        this.initRedisDictionaries(dictionary.getDictNameEn());
    }

    @Override
    @Transactional(rollbackFor = BusinessException.class)
    public void updateDictionary(DictionaryDTO dto) {
        Dictionary db = super.getById(dto.getId());
        redisUtil.del(Constants.RedisKeyCons.DICTIONARY.getCode() + db.getDictNameEn());
//        guavaCache.del(Constants.RedisKeyCons.DICTIONARY.getCode() + db.getDictNameEn());
        Dictionary dictionary;
        if (!Objects.equals(db.getId(), dto.getId())) {
            dictionary = this.nonExistsAndConvert(dto);
        } else {
            dictionary = BeanExUtils.convertTo(dto, Dictionary::new);
        }
        super.updateById(dictionary);
        this.initRedisDictionaries(dictionary.getDictNameEn());
    }

    @Override
    @Transactional(rollbackFor = BusinessException.class)
    public void removeDictionary(List<String> ids) {
        List<Dictionary> dictionaries = new ArrayList<>(super.listByIds(ids));
        super.removeByIds(ids);
        dictionaries.forEach(dictionary -> {
            dictionaryOptionService.deleteDictionaryOptionByDictId(dictionary.getId());
            redisUtil.del(Constants.RedisKeyCons.DICTIONARY.getCode() + dictionary.getDictNameEn());
//            guavaCache.del(Constants.RedisKeyCons.DICTIONARY.getCode() + dictionary.getDictNameEn());
        });
    }

    @Override
    public void initRedisDictionaries(String dictNameEn) {
        if (StringUtils.isBlank(dictNameEn)) {
            redisUtil.deleteKeys(Constants.RedisKeyCons.DICTIONARY.getCode());
          //  guavaCache.delPrefixKey(Constants.RedisKeyCons.DICTIONARY.getCode());
        }
        LambdaQueryWrapper<Dictionary> qw = Wrappers.lambdaQuery();
        qw.eq(StringUtils.isNotBlank(dictNameEn), Dictionary::getDictNameEn, dictNameEn);
        List<Dictionary> dictionaries = super.list(qw);
        dictionaries.forEach(dictionary -> {
            List<DictionaryOption> dictionaryOptions = dictionaryOptionService.selectByDictId(dictionary.getId());
            if (dictionaryOptions.isEmpty()) {
                redisUtil.del(Constants.RedisKeyCons.DICTIONARY.getCode() + dictionary.getDictNameEn());
               // guavaCache.del(Constants.RedisKeyCons.DICTIONARY.getCode() + dictionary.getDictNameEn());
                return;
            }
            List<Map<String, Object>> dictList = dictionaryOptions.stream().map(dictionaryOption -> {
                Map<String, Object> dict = new HashMap<>(4);
                dict.put("label", dictionaryOption.getDictLabel());
                dict.put("value", dictionaryOption.getDictValue());
                return dict;
            }).collect(Collectors.toList());
            redisUtil.set(Constants.RedisKeyCons.DICTIONARY.getCode() + dictionary.getDictNameEn(), dictList.toString(),30*60);
          //  guavaCache.put(Constants.RedisKeyCons.DICTIONARY.getCode() + dictionary.getDictNameEn(), dictList);
        });
    }

    @Override
    public Map<String, Object> queryDict() {
        return redisUtil.keys(Constants.RedisKeyCons.DICTIONARY.getCode());
//        return guavaCache.getAll(Constants.RedisKeyCons.DICTIONARY.getCode());
    }

    private Dictionary nonExistsAndConvert(DictionaryDTO dto) {
        LambdaQueryWrapper<Dictionary> qw = Wrappers.lambdaQuery();
        qw.eq(Dictionary::getDictNameEn, dto.getDictNameEn());
        if (super.count(qw) > 0) {
            throw new BusinessException(ResultCodeEnum.DICT_NAME_EN_EXISTS);
        }
        return BeanExUtils.convertTo(dto, Dictionary::new);
    }
}